// 引入所需模块
const http = require('http')
const path = require('path')
const socketIO = require('socket.io')
const fs = require('fs')
const crypto = require('crypto')
const config = global.config

function createSocketServer ({ app }) {
  const httpServer = http.createServer(app)
  // 创建socket.io 服务
  const io = socketIO(httpServer, {
    maxHttpBufferSize: 2 * 1e9, // 最大2G文件
    pingTimeout: 60000,
    httpCompression: {
      // Engine.IO options
      threshold: 2048, // defaults to 1024
      // Node.js zlib options
      chunkSize: 8 * 1024, // defaults to 16 * 1024
      windowBits: 14, // defaults to 15
      memLevel: 7, // defaults to 8
    },
    connectionStateRecovery: {
      // the backup duration of the sessions and the packets
      maxDisconnectionDuration: 5 * 60 * 1000,
      // whether to skip middlewares upon successful recovery
      skipMiddlewares: true,
    }
  })

  // 当 socket 连接时执行
  io.on('connection', (socket) => {
    console.log('客户端连接成功')
    // 客户端连接完成
    socket.emit('connected')
    // 当收到文件时处理
    socket.on('upload', (file, fileData) => {
      const { fileName } = fileData
      // 缓存分片文件
      const finalFilePath = path.join(config.uploadPath, fileName)
      fs.writeFileSync(finalFilePath, file)
      // 响应
      const data = {
        status: 200,
        success: 1,
        message: '上传成功',
        data: {
          name: fileName
        }
      }
      socket.emit('upload_response', data)
    })

    // 当收到文件分片时处理
    socket.on('upload-chunk', (chunk, chunkData) => {
      const { fileName, fileType, fileSize, chunkSize, chunkNumber, chunkTotal, sha256 } = chunkData
      // 缓存分片文件
      const tempFilePath = path.join(config.tempPath, `${fileName}.part${chunkNumber}`)
      fs.writeFileSync(tempFilePath, chunk)

      // 合并文件逻辑
      if (Number(chunkNumber) + 1 === Number(chunkTotal)) {
        const finalFilePath = path.join(config.uploadPath, fileName)
        const writeStream = fs.createWriteStream(finalFilePath)
        for (let i = 0; i < chunkTotal; i++) {
          const chunkPath = path.join(config.tempPath, `${fileName}.part${i}`)
          const data = fs.readFileSync(chunkPath) // 读取 chunk 文件
          writeStream.write(data)
          fs.unlinkSync(chunkPath) // 逐一删除 chunk 文件
        }
        writeStream.end()
      }

      // 响应
      const data = {
        status: 200,
        success: 1,
        message: '上传成功',
        data: {
          name: fileName,
          chunkNumber, chunkTotal,
          progress: (((chunkNumber + 1) / chunkTotal) * 100).toFixed(2)
        }
      }
      socket.emit('upload_trunk_response', data)
    })

    // 当客户端断开连接时
    socket.on('disconnect', () => {
      console.log('客户端断开连接')
    })
  })

  httpServer.listen(config.SOCKET_PORT, () => {
    console.log('Socket服务端->http://127.0.0.1:' + config.SOCKET_PORT)
  })
}

module.exports = {
  createSocketServer
}